package com.cdzx.quartz.config;

import com.cdzx.quartz.listener.CustomJobListener;
import com.cdzx.quartz.listener.CustomSchedulerListener;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Scheduler;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
@Configuration
public class QuartzConfig {

    public static final int cpuNum = Runtime.getRuntime().availableProcessors();

    @Resource
    private DataSource dataSource;
    @Resource
    private CustomSchedulerListener customSchedulerListener;
    @Resource
    private CustomJobListener customJobListener;

    @Bean
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean properties = new PropertiesFactoryBean();
        properties.setLocation(new ClassPathResource("./quartz.properties"));
        properties.afterPropertiesSet();
        return properties.getObject();
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
        factoryBean.setAutoStartup(true);
        factoryBean.setStartupDelay(10);
        factoryBean.setOverwriteExistingJobs(true);
        factoryBean.setWaitForJobsToCompleteOnShutdown(true);
        factoryBean.setDataSource(dataSource);
        factoryBean.setSchedulerName("cluster_scheduler");
        factoryBean.setSchedulerListeners(customSchedulerListener);
        factoryBean.setGlobalJobListeners(customJobListener);
        factoryBean.setApplicationContextSchedulerContextKey("application_quartz");
        factoryBean.setQuartzProperties(quartzProperties());
        factoryBean.setTaskExecutor(taskExecutor());
        return factoryBean;
    }

    @Bean
    public Scheduler scheduler() throws Exception {
        return schedulerFactoryBean().getScheduler();
    }

    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        // 配置核心线程池数量
        taskExecutor.setCorePoolSize(cpuNum / 2);
        // 配置最大线程池数量
        taskExecutor.setMaxPoolSize(cpuNum / 2);
        /// 线程池所使用的缓冲队列
        taskExecutor.setQueueCapacity(5);
        // 等待时间 （默认为0，此时立即停止），并没等待xx秒后强制停止
        taskExecutor.setAwaitTerminationSeconds(60);
        // 空闲线程存活时间
        taskExecutor.setKeepAliveSeconds(60);
        // 等待任务在关机时完成--表明等待所有线程执行完
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        // 线程池名称前缀
        taskExecutor.setThreadNamePrefix("thread-pool-");
        // 线程池拒绝策略
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
        // 线程池初始化
        taskExecutor.initialize();
        log.info("线程池初始化......");
        return taskExecutor;
    }
}
